#ifndef _MEMORY_H
#define _MEMORY_H

#include <types.h>
#include <list.h>
#include <malloc.h>

enum memory_type {
	MT_DEVICE,
	MT_ROM,
	MT_SRAM,
	MT_SDRAM,
	MT_NR,
};

typedef enum memory_type memory_type_t;

enum memory_zone_type {
	MZ_DMA,
	MZ_NORMAL,
	MZ_NR,
};

typedef enum memory_zone_type memory_zone_t;

enum memory_map_type {
	MMT_DEVICE,
	MMT_ROM,
	MMT_RAM,
	MMT_DMA,
	MMT_NR,
};

typedef enum memory_map_type memory_map_t;

struct memory_bank {
	char *name;
	uint32_t start_addr;
	uint32_t length;
	memory_type_t type;
	struct list_head n_bank_list;
};

struct memory_allocator;

struct memory_zone {
	char *name;
	uint32_t start_addr;
	uint32_t length;
	memory_zone_t type;
	struct memory_allocator *allocator;	
	unsigned int alloc_end;
	struct memory_bank *bank;
	unsigned int footprint;
	void *priv;
	struct list_head n_zone_list;
	struct list_head n_zone_type_list;
};

struct memory_map {    
    uint32_t virt_addr;  
    uint32_t phys_addr;  
    uint32_t length;     
	memory_map_t type;
};  

extern struct list_head memory_banks;

#define for_each_memory_bank(p)		\
	list_for_each(p, &memory_banks)

int memory_bank_add(struct memory_bank *bank, unsigned int count);

extern struct list_head memory_zones;
 
#define for_each_memory_zone(p)		\
	list_for_each(p, &memory_zones)

extern struct list_head memory_dma_zones;
 
#define for_each_dma_memory_zone(p)		\
	list_for_each(p, &memory_dma_zones)

extern struct list_head memory_sram_zones;
 
#define for_each_sram_memory_zone(p)		\
	list_for_each(p, &memory_sram_zones)

extern struct list_head memory_sdram_zones;
 
#define for_each_sdram_memory_zone(p)		\
	list_for_each(p, &memory_sdram_zones)

#define zone_set_priv(z, v)	((z)->priv = (void *)(v))
#define zone_get_priv(z)	((z)->priv)

int memory_zone_add(struct memory_zone *zone, unsigned int count);

int memory_map_init(void);

int memory_init(void);

#endif /* _MEMORY_H */

